#pragma once
#include "kdealloc.h"
#include "kstlbool.h"
#include "klist.h"


#include <cstddef>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct KstlCache KstlCache;

typedef struct KstlCacheSettings {
    size_t          itemSize;
    size_t          maxElements;
    size_t          ttl;
    KstlDeallocator dealloc;
} KstlCacheSettings;

typedef struct KstlCacheIterator {
    KstlCache*       handle;
    KstlListIterator current;
} KstlCacheIterator;

#define KC_FOR_EACH(handle, it)                                                                                        \
    for (KstlCacheIterator(it) = KstlCacheIteratorBegin((handle)); !KstlCacheIteratorIsEnd((it));                      \
         KstlCacheIteratorNext(&(it)))

KstlCache* KstlCacheInit(KstlCacheSettings settings);
void       KstlCacheRelease(KstlCache* cache);

size_t KstlCacheSize(KstlCache* cache);

int KstlCacheAdd(KstlCache* cache, const void* key, size_t keyLength, void* item);
int KstlCacheGet(KstlCache* cache, const void* key, size_t keyLength, void* item);

int  KstlCacheRemove(KstlCache* cache, const void* key, size_t keyLength);
void KstlCacheRemoveIt(KstlCache* cache, KstlCacheIterator it);

void KstlCacheClear(KstlCache* cache);

// iterators
KstlCacheIterator KstlCacheIteratorBegin(KstlCache* handle);
KstlCacheIterator KstlCacheIteratorEnd(KstlCache* handle);

void KstlCacheIteratorNext(KstlCacheIterator* it);

bool KstlCacheIteratorIsEnd(KstlCacheIterator it);

void*  KstlCacheIteratorValue(KstlCacheIterator it);
void*  KstlCacheIteratorKey(KstlCacheIterator it);
size_t KstlCacheIteratorKeySize(KstlCacheIterator it);

#ifdef __cplusplus
}  // extern "C"
#endif